package com.monkey.luffer.springboot.demo.basis.kcc.test.lianji.majiang;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author jiahong.liu
 */
@Data
public class Player {
    PlayerHand playerHand = new PlayerHand();
    String name;
    boolean isManual;
    Socket socket;
    Seat seat;
    int score = 0;

    public Player (String name, Seat seat) {
        this.name = name;
        this.seat = seat;
    }

    public Player (String name, Socket socket, boolean isManual, Seat seat) {
        this.isManual = isManual;
        this.name = name;
        this.socket = socket;
        this.seat = seat;
    }

    public PlayerStatus checkIfGetCard(Majiang.Card card, boolean isZimo, int handoutIndex) throws InterruptedException {
        PlayerStatus playerStatus = new PlayerStatus();
        if (isZimo) {
            playerStatus.setGetCard(card);
            playerStatus.setZimo(true);
        }

        if (isManual) {
            return checkIfGetCardByManualNotCard(card, isZimo, handoutIndex);
        }
        System.out.println(name + "手牌为：" + playerHand.printCard() + "摸到的牌为：" + card.printCard());
        // 先检查是否胡牌
        if (BaseRule.isHu(playerHand, card)) {
            playerStatus.setStatus(Status.HU);
            return playerStatus;
        }

        // 检查牌中的暗GANG
        if(isZimo) {
            playerHand.putInCard(card);
            if (getGang(playerHand.getAll()).size() > 0) {
                playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                playerHand.setCardNum(playerHand.cardNum - 4);
                playerStatus.setStatus(Status.AN);
                return playerStatus;
            } else {
                playerHand.removeCard(card);
            }
        }

        // 检查peng中的杠
        if (isZimo) {
            if (playerHand.getPeng().contains(card.getNumber() + card.getSuit().getSalt())) {
                // 可以杠
                playerStatus.setStatus(Status.GANG);
                return playerStatus;
            }
        }

        playerHand.setJiang(getJiang(playerHand.getAll()));
        playerHand.setKez(getKe(playerHand.getAll()));
        // 去掉对中的刻子
        for(int i = 0; i < playerHand.getJiang().size(); i++) {
            int jiang = playerHand.getJiang().get(i);
            if (playerHand.getKez().contains(jiang)) {
                playerHand.getJiang().remove(i);
                if ( playerHand.getJiang().size() <= i) {
                    break;
                }
            }
        }

        // 有扛必杠
        if (playerHand.getKez().contains(card.getNumber() + card.getSuit().getSalt())) {
            // 删除所有杠掉的牌
            playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
            playerHand.setCardNum(playerHand.cardNum - 3);
            playerStatus.setStatus(Status.GANG);
            return playerStatus;
        }


        if (!isZimo) {
            // 有多余的对则碰
            if (playerHand.getJiang().size() >= 2 && playerHand.getJiang().contains(card.getNumber() + card.getSuit().getSalt())) {
                playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                playerHand.setCardNum(playerHand.cardNum - 2);
                playerStatus.setStatus(Status.PENG);
                playerHand.getPeng().add(card.getNumber() + card.getSuit().getSalt());
                return playerStatus;
            }

            if (Seat.getNext(handoutIndex) == this.seat) {
                // 有吃就吃
                List<Integer> cards =  removeAllShun(playerHand.getAll());
                List<TwoCard> twoCard = new ArrayList<>();
                boolean eat = canEat(card, twoCard, cards);
                if (eat) {
                    playerStatus.setEatCard(twoCard.get(0));
                    playerStatus.setStatus(Status.EAT);
                    return playerStatus;
                }
            }

        } else {
            playerHand.putInCard(card);
        }
        playerStatus.setStatus(Status.PASS);
        return playerStatus;

    }

    public PlayerStatus checkIfGetCardByManual(Majiang.Card card, boolean isZimo, int handoutIndex) throws InterruptedException {
        PlayerStatus playerStatus = new PlayerStatus();
        if (isZimo) {
            playerStatus.setGetCard(card);
            playerStatus.setZimo(true);
            sendMessage(socket,("您的手牌为：" + this.playerHand.printCard() + "摸到的牌为：" + card.printCard() + "\n").getBytes(StandardCharsets.UTF_16));
        }

        // 先检查是否胡牌
        if (BaseRule.isHu(playerHand, card)) {
            sendMessage(socket, ("您的手牌为：" + this.playerHand.printCard() + "\n").getBytes(StandardCharsets.UTF_16));
            sendMessage(socket,("A您已胡牌，输入 Y-胡，N-不胡\n").getBytes(StandardCharsets.UTF_16));
            String line = waitMessage();
            if ("Y".equalsIgnoreCase(line)) {
                playerStatus.setStatus(Status.HU);
                return playerStatus;
            }
        }

        // 检查牌中的暗GANG
        if (isZimo) {
            playerHand.putInCard(card);
            if (getGang(playerHand.getAll()).size() > 0) {
                sendMessage(socket,("A您可以暗杠，输入 Y-杠，N-不杠\n").getBytes(StandardCharsets.UTF_16));
                String line  = waitMessage();
                if ("Y".equalsIgnoreCase(line)) {
                    playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                    playerHand.setCardNum(playerHand.cardNum - 4);
                    playerStatus.setStatus(Status.AN);
                    return playerStatus;
                }
            } else {
                playerHand.removeCard(card);
            }

            // 检查peng中的杠
            if (playerHand.getPeng().contains(card.getNumber() + card.getSuit().getSalt())) {
                // 可以杠
                sendMessage(socket,("A您可以暗杠，输入 Y-杠，N-不杠\n").getBytes(StandardCharsets.UTF_16));
                String line  = waitMessage();
                if ("Y".equalsIgnoreCase(line)) {
                    playerStatus.setStatus(Status.GANG);
                    return playerStatus;
                }
            }
        }


        // 检查牌中的kez和jiang
        playerHand.setJiang(getJiang(playerHand.getAll()));
        playerHand.setKez(getKe(playerHand.getAll()));
        // 去掉对中的刻子
        for(int i = 0; i < playerHand.getJiang().size(); i++) {
            int jiang = playerHand.getJiang().get(i);
            if (playerHand.getKez().contains(jiang)) {
                playerHand.getJiang().remove(i);
                if ( playerHand.getJiang().size() <= i) {
                    break;
                }
            }
        }



        if (!isZimo) {
            boolean canGang = false;
            boolean canPeng = false;
            boolean canEat = false;
            List<TwoCard> eatArr = new ArrayList<>();
            if (playerHand.getKez().contains(card.getNumber() + card.getSuit().getSalt())) {
                canGang = true;
            }

            if (playerHand.getJiang().size() >= 1 && playerHand.getJiang().contains(card.getNumber() + card.getSuit().getSalt())) {
                canPeng = true;
            }

            if (Seat.getNext(handoutIndex) == this.seat) {
                canEat = canEat(card, eatArr);
            }

            if(canGang && canEat) {
                sendMessage(socket, ("您的手牌为：" + this.playerHand.printCard() + "\n").getBytes(StandardCharsets.UTF_16));
                sendMessage(socket, ("A您可以杠或碰"  + card.printCard() + "输入 G-杠，Y-碰，E-吃，P-pass\n").getBytes(StandardCharsets.UTF_16));
                String line = waitMessage();
                // 删除所有杠掉的牌
                if ("G".equalsIgnoreCase(line)) {
                    playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                    playerHand.setCardNum(playerHand.cardNum - 3);
                    playerStatus.setStatus(Status.GANG);
                    return playerStatus;
                } else if ("Y".equalsIgnoreCase(line)){
                    playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                    playerHand.getAll().add(card.getNumber() + card.getSuit().getSalt());
                    playerHand.getPeng().add(card.getNumber() + card.getSuit().getSalt());
                    Collections.sort(playerHand.getAll());
                    playerHand.setCardNum(playerHand.cardNum - 2);
                    playerStatus.setStatus(Status.PENG);
                    return playerStatus;
                } else if("E".equalsIgnoreCase(line)) {
                    eat(eatArr, playerStatus);
                    playerStatus.setStatus(Status.EAT);
                    return playerStatus;
                } else {
                    playerStatus.setStatus(Status.PASS);
                    return playerStatus;
                }
            } else if(canGang) {
                sendMessage(socket, ("您的手牌为：" + this.playerHand.printCard() + "\n").getBytes(StandardCharsets.UTF_16));
                sendMessage(socket, ("A您可以杠或碰"  + card.printCard() + "输入 G-杠，Y-碰，P-pass\n").getBytes(StandardCharsets.UTF_16));
                String line = waitMessage();
                // 删除所有杠掉的牌
                if ("G".equalsIgnoreCase(line)) {
                    playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                    playerHand.setCardNum(playerHand.cardNum - 3);
                    playerStatus.setStatus(Status.GANG);
                    return playerStatus;
                } else if ("Y".equalsIgnoreCase(line)){
                    playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                    playerHand.getAll().add(card.getNumber() + card.getSuit().getSalt());
                    playerHand.getPeng().add(card.getNumber() + card.getSuit().getSalt());
                    Collections.sort(playerHand.getAll());
                    playerHand.setCardNum(playerHand.cardNum - 2);
                    playerStatus.setStatus(Status.PENG);
                    return playerStatus;
                } else {
                    playerStatus.setStatus(Status.PASS);
                    return playerStatus;
                }
            } else if (canPeng && canEat) {
                sendMessage(socket, ("您的手牌为：" + this.playerHand.printCard() + "\n").getBytes(StandardCharsets.UTF_16));
                sendMessage(socket, ("A您可以碰 "  + card.printCard() + "输入 Y-碰，E-吃，P-pass\n").getBytes(StandardCharsets.UTF_16));
                String line = waitMessage();
                // 删除所有碰掉的牌
                if ("Y".equalsIgnoreCase(line)) {
                    playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                    playerHand.setCardNum(playerHand.cardNum - 2);
                    playerHand.getPeng().add(card.getNumber() + card.getSuit().getSalt());
                    playerStatus.setStatus(Status.PENG);
                    return playerStatus;
                } else if("E".equalsIgnoreCase(line)) {
                    eat(eatArr, playerStatus);
                    playerStatus.setStatus(Status.EAT);
                    return playerStatus;
                } else {
                    playerStatus.setStatus(Status.PASS);
                    return playerStatus;
                }
            } else if (canPeng) {
                sendMessage(socket, ("您的手牌为：" + this.playerHand.printCard() + "\n").getBytes(StandardCharsets.UTF_16));
                sendMessage(socket, ("A您可以碰 "  + card.printCard() + "输入 Y-碰，P-pass\n").getBytes(StandardCharsets.UTF_16));
                String line = waitMessage();
                // 删除所有碰掉的牌
                if ("Y".equalsIgnoreCase(line)) {
                    playerHand.getPeng().add(card.getNumber() + card.getSuit().getSalt());
                    playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                    playerHand.setCardNum(playerHand.cardNum - 2);
                    playerStatus.setStatus(Status.PENG);
                    return playerStatus;
                } else {
                    playerStatus.setStatus(Status.PASS);
                    return playerStatus;
                }
            } else if (canEat) {
                sendMessage(socket, ("您的手牌为：" + this.playerHand.printCard() + "\n").getBytes(StandardCharsets.UTF_16));
                sendMessage(socket, ("A您可以吃 "  + card.printCard() + "输入 Y-吃，P-pass\n").getBytes(StandardCharsets.UTF_16));
                String line = waitMessage();
                if("Y".equalsIgnoreCase(line)) {
                    eat(eatArr, playerStatus);
                    playerStatus.setStatus(Status.EAT);
                    return playerStatus;
                }
            }

        } else {
            playerHand.putInCard(card);
        }

        playerStatus.setStatus(Status.PASS);
        return playerStatus;

    }

    public PlayerStatus checkIfGetCardByManualNotCard(Majiang.Card card, boolean isZimo, int handoutIndex) throws InterruptedException {
        PlayerStatus playerStatus = new PlayerStatus();
        playerStatus.setPlayer(true);
        if (isZimo) {
            playerStatus.setGetCard(card);
            playerStatus.setZimo(true);
            sendMessage(socket,("您的手牌为：" + this.playerHand.printCard() + "摸到的牌为：" + card.printCard() + "\n").getBytes(StandardCharsets.UTF_16));
        }

        // 先检查是否胡牌
        if (BaseRule.isHu(playerHand, card)) {
            sendMessage(socket, ("您的手牌为：" + this.playerHand.printCard() + "\n").getBytes(StandardCharsets.UTF_16));
            sendMessage(socket,("A您已胡牌，输入 Y-胡，N-不胡\n").getBytes(StandardCharsets.UTF_16));
            String line = waitMessage();
            if ("Y".equalsIgnoreCase(line)) {
                playerStatus.setStatus(Status.HU);
                return playerStatus;
            }
        }

        // 检查牌中的暗GANG
        if (isZimo) {
            playerHand.putInCard(card);
            if (getGang(playerHand.getAll()).size() > 0) {
                sendMessage(socket,("A您可以暗杠，输入 Y-杠，N-不杠\n").getBytes(StandardCharsets.UTF_16));
                String line  = waitMessage();
                if ("Y".equalsIgnoreCase(line)) {
                    playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                    playerHand.setCardNum(playerHand.cardNum - 4);
                    playerStatus.setStatus(Status.AN);
                    return playerStatus;
                }
            } else {
                playerHand.removeCard(card);
            }

            // 检查peng中的杠
            if (playerHand.getPeng().contains(card.getNumber() + card.getSuit().getSalt())) {
                // 可以杠
                sendMessage(socket,("A您可以暗杠，输入 Y-杠，N-不杠\n").getBytes(StandardCharsets.UTF_16));
                String line  = waitMessage();
                if ("Y".equalsIgnoreCase(line)) {
                    playerStatus.setStatus(Status.GANG);
                    return playerStatus;
                }
            }
        }


        // 检查牌中的kez和jiang
        playerHand.setJiang(getJiang(playerHand.getAll()));
        playerHand.setKez(getKe(playerHand.getAll()));
        // 去掉对中的刻子
        for(int i = 0; i < playerHand.getJiang().size(); i++) {
            int jiang = playerHand.getJiang().get(i);
            if (playerHand.getKez().contains(jiang)) {
                playerHand.getJiang().remove(i);
                if ( playerHand.getJiang().size() <= i) {
                    break;
                }
            }
        }



        if (!isZimo) {
            playerStatus.setCurCard(card);
            boolean canGang = false;
            boolean canPeng = false;
            boolean canEat = false;
            List<TwoCard> eatArr = new ArrayList<>();
            if (playerHand.getKez().contains(card.getNumber() + card.getSuit().getSalt())) {
                playerStatus.setCanGang(true);
                canGang = true;
            }

            if (playerHand.getJiang().size() >= 1 && playerHand.getJiang().contains(card.getNumber() + card.getSuit().getSalt())) {
                playerStatus.setCanPeng(true);
                canPeng = true;
            }

            if (Seat.getNext(handoutIndex) == this.seat) {
                canEat = canEat(card, eatArr);
            }
            playerStatus.setCanEat(canEat);
            playerStatus.setCanEatCard(eatArr);

        } else {
            playerHand.putInCard(card);
        }

        playerStatus.setStatus(Status.PASS);
        return playerStatus;

    }

    public void eat(List<TwoCard> eatArr, PlayerStatus playerStatus) {
        if (eatArr.size() > 1) {
            StringBuilder message = new StringBuilder("A请选择吃的牌组，输入数字即可:");
            for (int i = 0; i < eatArr.size(); i ++) {
                message.append(i + 1).append("-").append(eatArr.get(i).printCard());
            }
            message.append("\n");
            sendMessage(socket, message.toString().getBytes(StandardCharsets.UTF_16));
            String msg = waitMessage();
            int num;
            if (!Majiang.Card.isNum(msg) && (Integer.parseInt(msg) - 1) > eatArr.size() ) {
                // 输入错误默认选择第一组牌
                num = 0;
            } else {
                num = Integer.parseInt(msg) - 1;
            }
            playerStatus.setEatCard(eatArr.get(num));
        } else {
            playerStatus.setEatCard(eatArr.get(0));
        }

    }

    public boolean canEat(Majiang.Card card, List<TwoCard> arr) {
        // 字牌不能吃
        if (card.getSuit().getSalt() > 30) {
            return false;
        }
        int carNum = card.getNumber() + card.getSuit().getSalt();
        // 当前牌的几种模式
        // 第一张
        if (playerHand.getAll().contains(carNum + 1) && playerHand.getAll().contains(carNum + 2)) {
            arr.add(new TwoCard(carNum + 1, carNum + 2));
            return true;
        }
        // 第二张
        if (playerHand.getAll().contains(carNum - 1) && playerHand.getAll().contains(carNum + 1)) {
            arr.add(new TwoCard(carNum - 1, carNum + 1));
            return true;
        }
        // 第三张
        if (playerHand.getAll().contains(carNum - 1) && playerHand.getAll().contains(carNum - 2)) {
            arr.add(new TwoCard(carNum - 1, carNum - 2));
            return true;
        }
        return false;
    }


    public boolean canEat(Majiang.Card card, List<TwoCard> arr, List<Integer> cards) {
        // 字牌不能吃
        if (card.getSuit().getSalt() > 30) {
            return false;
        }
        int carNum = card.getNumber() + card.getSuit().getSalt();
        // 当前牌的几种模式
        // 第一张
        if (cards.contains(carNum + 1) && cards.contains(carNum + 2)) {
            arr.add(new TwoCard(carNum + 1, carNum + 2));
            return true;
        }
        // 第二张
        if (cards.contains(carNum - 1) && cards.contains(carNum + 1)) {
            arr.add(new TwoCard(carNum - 1, carNum + 1));
            return true;
        }
        // 第三张
        if (cards.contains(carNum - 1) && cards.contains(carNum - 2)) {
            arr.add(new TwoCard(carNum - 1, carNum - 2));
            return true;
        }
        return false;
    }

    /**
     * 获取牌组中所有的“将”
     *
     * @param cards 牌组
     * @return 所有的“将”组成的数组
     */
    private static List<Integer> getJiang(List<Integer> cards) {
        List<Integer> jiang = new ArrayList<>();
        if (null != cards && cards.size() > 1) {
            for (int i = 0; i < cards.size() - 1; i++) {
                if (cards.get(i).equals(cards.get(i + 1))) {
                    jiang.add(cards.get(i));
                    i++;
                }
            }
        }
        return jiang;
    }

    /**
     * 去掉牌组中所有的刻子
     *
     * @param cards 牌组
     */
    private static List<Integer> getKe(List<Integer> cards) {
        List<Integer> ke = new ArrayList<>();
        for (int i = 0; i < cards.size() - 2; i++) {
            if (cards.get(i) .equals(cards.get(i + 1))  && cards.get(i).equals(cards.get(i + 2))) {
                ke.add(cards.get(i));
            }
        }
        return ke;
    }


    /**
     * 去掉牌组中所有的刻子
     *
     * @param cards 牌组
     */
    private static List<Integer> getGang(List<Integer> cards) {
        List<Integer> gang = new ArrayList<>();
        for (int i = 0; i < cards.size() - 3; i++) {
            if (cards.get(i) .equals(cards.get(i + 1))  && cards.get(i).equals(cards.get(i + 2)) && cards.get(i).equals(cards.get(i + 3))) {
                gang.add(cards.get(i));
            }
        }
        return gang;
    }

    public void putOutCard(Majiang.Card card) {
        this.playerHand.removeCard(card);
    }

    public Majiang.Card putOutCard(List<Integer> all) {
        // 先删除刻子，再顺子，再删除一对，剩下的一个个遍历
        all = removeAllKe(all);
        all = removeAllShun(all);
        all = removeOneJiang(all);
        Integer temp = 0;
        Majiang.Card card = null;
        // 从后往前遍历
        for (int i = all.size() - 1; i >= 0; i--) {
            // 有字先打字
            if (all.get(i) > 40) {
                temp = all.get(i);
                playerHand.removeCard(temp);
                card = Majiang.Card.getCard(temp);
                break;
            }

            if (i != 0 && (all.get(i).equals(all.get(i - 1)))) {
                i--;
                continue;
            }

            if( i != 0 && ((all.get(i) - 1) == (all.get(i - 1)))) {
                i--;
                continue;
            }

            temp = all.get(i);
            playerHand.removeCard(temp);
            card = Majiang.Card.getCard(temp);
            break;
        }

        if (temp.equals(0)) {
            // 如果找不到手上可以打的牌，则随便打一张
            card = Majiang.Card.getCard(playerHand.getAll().get(0));
            playerHand.removeCard(playerHand.getAll().get(0));
        }
        return card;
    }


    public boolean hasCard(Majiang.Card card) {
        return this.getPlayerHand().hasCard(card);
    }

    /**
     * 去掉牌组中所有的刻子
     *
     */
    public static List<Integer> removeAllKe(List<Integer> all) {
        List<Integer> tmp = new ArrayList<>(all);
        for (int i = 0; i < all.size() - 2; i++) {
            if (all.get(i).equals(all.get(i + 1))  && all.get(i + 1).equals(all.get(i + 2))) {
                Integer ele = all.get(i);
                tmp.removeIf(integer -> integer.equals(ele));
            }
        }
        return tmp;
    }

    /**
     * 去掉牌组中所有的顺子
     *
     */
    private static List<Integer> removeAllShun(List<Integer> all) {
        List<Integer> tmp = new ArrayList<>(all);
        for (int i = 0; i < all.size() - 2; i++) {
            if ((all.get(i) + 1) == (all.get(i + 1)) && all.get(i + 1) + 1 == all.get(i + 2)) {
                tmp.remove(all.get(i));
                tmp.remove(all.get(i + 1));
                tmp.remove(all.get(i + 2));
                i += 2;
            }
        }
        return tmp;
    }

    private static boolean hasShun(List<Integer> all, List<Integer> remaining) {
        for (int i = 0; i < remaining.size() - 2; i++) {
            if ((remaining.get(i) + 1) == (remaining.get(i + 1)) && remaining.get(i + 1) + 1 == remaining.get(i + 2)) {
                all.remove(remaining.get(i));
                all.remove(remaining.get(i + 1));
                all.remove(remaining.get(i + 2));
                return true;
            }
        }
        return false;
    }

    private static List<Integer> removeOneJiang(List<Integer> all) {
        List<Integer> tmp = new ArrayList<>(all);
        for (int i = 0; i < all.size() - 1; i++) {
            if (all.get(i).equals(all.get(i + 1))) {
                Integer ele = all.get(i);
                tmp.removeIf(integer -> integer.equals(ele));
            }
        }
        return tmp;
    }

    @AllArgsConstructor
    public enum Status {
        /**
         *
         */
        EAT("0", "吃"),
        PENG("1", "碰"),
        HU("2", "胡"),
        GANG("3", "杠"),
        PASS("4", ""),
        AN("5", "暗杠"),;

        String code;
        String value;
    }

    public void sendMessage(Socket socket, byte[] by) {
        // 将服务器接收到的消息发送给除了发送方以外的其他客户端
        BufferedOutputStream ps = null;
        try {
            ps = new BufferedOutputStream(socket.getOutputStream());
            ps.write(by);   // 写入输出流，将内容发送给客户端的输入流
            ps.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public String waitMessage() {
        try {
            BufferedReader ois = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (true) {
                String line;
                while (( line = ois.readLine()) != null) {
                    return line.replace("\n", "");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Data
    public static class PlayerStatus {
        boolean isZimo;
        Status status;
        Majiang.Card getCard;
        TwoCard eatCard;
        Socket socket;
        String message;
        boolean isPlayer;
        boolean canGang = false;
        boolean canPeng = false;
        boolean canEat = false;
        Majiang.Card curCard;
        List<TwoCard> canEatCard;
    }

    @AllArgsConstructor
    @Getter
    public enum Seat {
        /**
         *
         */
        EAST(0),
        SOUTH(1),
        WEST(2),
        NORTH(3),;
        private int sort;

        public static Seat getNext(int cur) {
            for(Seat seat : Seat.values()) {
                if (cur + 1 == seat.getSort()) {
                    return seat;
                }

                if (cur + 1 > 4) {
                    return Seat.EAST;
                }
            }
            return EAST;
        }

        public static Seat getSortByNum(int cur) {
            for(Seat seat : Seat.values()) {
                if (cur  == seat.getSort()) {
                    return seat;
                }
            }
            return null;
        }
    }

    @Data
    static class TwoCard {
        Majiang.Card card1;
        Majiang.Card card2;

        public TwoCard(Integer card1, Integer card2) {
            this.card1 = Majiang.Card.getCard(card1);
            this.card2 = Majiang.Card.getCard(card2);
        }

        public String printCard () {
            return card1.printCard() + card2.printCard();
        }
    }
}
